package xj.toolkit.fsm.helper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import xj.toolkit.base.Sender;
import xj.toolkit.base.TransportUtils;
import xj.toolkit.ebus.EventBus;
import xj.toolkit.fsm.FSMContext;
import xj.toolkit.fsm.FiniteStateMachine;
import xj.toolkit.fsm.tmpl.annotation.OnEnter;
import xj.toolkit.fsm.tmpl.annotation.StateTemplate;
import xj.toolkit.util.MutableIdentifyable;
import xj.toolkit.util.MutablePropertyable;

public abstract class BaseBiz<Q extends MutableIdentifyable<T>, T extends MutableIdentifyable<T>> {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    protected static final Logger timeoutLogger = LoggerFactory.getLogger("timeoutLogger");
    public static final String FSM_CONTEXT_REQ = "REQUEST";
    public static final String FSM_CONTEXT_REP = "RESPONSE";

    protected EventBus eventBus;
    protected int timeout;

    @SuppressWarnings("unchecked")
    protected Q getRequest(FSMContext ctx) {
        return (Q) ctx.getProperty(FSM_CONTEXT_REQ);
    }

    protected void setRequest(FSMContext ctx, Q request) {
        ctx.setProperty(FSM_CONTEXT_REQ, request);
    }
    
    protected void addReqRespOnCtx(FSMContext ctx, Q request, T response) {
    	response.setIdentification(request.getIdentification());
    	setRequest(ctx, request);
    	setResponse(ctx, response);
    }

    @SuppressWarnings("unchecked")
    protected T getResponse(FSMContext ctx) {
        return (T) ctx.getProperty(FSM_CONTEXT_REP);
    }

    protected void setResponse(FSMContext ctx, T response) {
        ctx.setProperty(FSM_CONTEXT_REP, response);
    }

    public EventBus getEventBus() {
        return eventBus;
    }

    public void setEventBus(EventBus eventBus) {
        this.eventBus = eventBus;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
    
    @StateTemplate
    protected class SendResp {
        @OnEnter
        boolean enter(FiniteStateMachine fsm, FSMContext ctx) {
            // 处理向client返回
            if (getResponse(ctx) != null) {
                Q request = getRequest(ctx);
                T response = getResponse(ctx);
                // send response
                @SuppressWarnings("unchecked")
				Sender<T> sender = (Sender<T>) TransportUtils.getSenderOf((MutablePropertyable<String, Object>)request);
                if (logger.isDebugEnabled()) {
                    logger.debug("SendClientRespState={}", response);
                }
                if (sender != null) {
                    sender.send(request, response);
                } else {
                    logger.error("getSender error!");
                }
                if (ctx.getEndReason() == null) {
                    ctx.setEndReason(request.getClass().getSimpleName());
                }
                return false;
            } else {
                logger.error("getResponse error!");
                return false;
            }
        }
    }
}
